# -*- coding: utf-8 -*-
from celery import platforms
from celery import Celery
import time
from connection_yunwei import ConnectionTask
from elasticsearch import Elasticsearch
import sys
import logging
import json

platforms.C_FORCE_ROOT = True
elk_request_status = Celery('elk_request_status_worker', broker="amqp://blm:blm123@192.168.0.67//")
elk_request_status.conf.update(
    result_expires=3600,
    task_serializer='json',
    accept_content=['json'],
    result_serializer='json',
    timezone='Asia/Shanghai',
    worker_max_tasks_per_child=200,
    worker_disable_rate_limits=True,
    task_create_missing_queues=True,
)

'''
    统计某时间段内 某域名访问返回的状态码的数量
    300～399：重定向
    400～499：客户端错误
    500～599：服务器错误
'''


class ELKRquestStatus(ConnectionTask):
    logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                        level=logging.INFO)

    @property
    def pro_mdb(self):
        return super().pmdb_master

    @property
    def rdb(self):
        return super().rdb_zabbix(0)

    _static_stg_es = {}

    def elk_es(self, collection, mappings=None):
        if ConnectionTask._static_stg_es.get(collection) is None:
            _es = Elasticsearch(["192.168.1.78:9200"],
                                http_auth=('elastic', '1CHYC5IO6TrgZM66kyOw'),
                                # sniff before doing anything
                                sniff_on_start=True,
                                # refresh nodes after a node fails to respond
                                sniff_on_connection_fail=True,
                                # and also every 60 seconds
                                sniffer_timeout=60)
            # ignore 400 cause by IndexAlreadyExistsException when creating an index
            _es.indices.create(index=collection, body=mappings, ignore=[400, 401, 404])
            # ignore 404 and 400
            # _es.indices.delete(index=collection, ignore=[400, 404])
            ConnectionTask._static_stg_es[collection] = _es
        return ConnectionTask._static_stg_es[collection]


@elk_request_status.task(base=ELKRquestStatus, bind=True, max_retries=3)
def get_elk_request_status_by_appcode(self, app_code, today, start_, end_,i):
    '''
        根据 传入的appCode拼接域名 获取elk中的访问该域名的返回状态码
        2020-07-13
    '''
    _es = Elasticsearch(["192.168.1.78:9200"],
                        http_auth=('elastic', '1CHYC5IO6TrgZM66kyOw'),
                        # sniff before doing anything
                        sniff_on_start=True,
                        # refresh nodes after a node fails to respond
                        sniff_on_connection_fail=True,
                        # and also every 60 seconds
                        sniffer_timeout=60)
    domain_name = '{}.otosaas.com'.format(app_code)
    # requset_status = [400, 401, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 500, 501,
    #                   502, 503, 504, 505]
    # for i in requset_status:
    es_search_body = {
        "aggs": {
            "3": {
                "range": {
                    "field": "request_status",
                    "ranges": [
                        {
                            "from": 400,
                            "to": 599
                        }
                    ],
                    "keyed": True
                },
                # "aggs": {
                #     "5": {
                #         "range": {
                #             "field": "request_status",
                #             "ranges": [
                #                 {
                #                     "from": 404,
                #                     "to": 405
                #                 }
                #             ],
                #             "keyed": True
                #         }
                #     }
                # }
            }
        },
        "size": 0,
        "_source": {
            "excludes": []
        },
        "stored_fields": [
            "*"
        ],
        "script_fields": {},
        "docvalue_fields": [
            {
                "field": "@timestamp",
                "format": "date_time"
            },
            {
                "field": "timestamp",
                "format": "date_time"
            }
        ],
        "query": {
            "bool": {
                "must": [
                    {
                        "match_all": {}
                    },
                    {
                        "match_all": {}
                    },
                    {
                        "match_phrase": {
                            "httphost": {
                                "query": domain_name
                            }
                        }
                    },
                    {
                        "match_phrase": {
                            "request_status": {
                                "query": i
                            }
                        }
                    },
                    {
                        "range": {
                            "timestamp": {
                                "gte": start_,
                                "lte": end_,
                                "format": "epoch_millis"
                            }
                        }
                    }
                ],
                "filter": [],
                "should": [],
                "must_not": []
            }
        }
    }

    es_obj = self.elk_es('otosaas_qlllog-{}'.format(today))
    resp_data = es_obj.search(
        index='otosaas_qlllog-*',
        # doc_type='doc',
        body=es_search_body,
    )
    # count_3xx = count_4xx = count_5xx = 0
    # ck = 1
    try:
        # ckk = resp_data['aggregations']['3']['buckets']['400.0-599.0']['5']['buckets']
        ckk = resp_data['aggregations']['3']['buckets']['400.0-599.0']['doc_count']
    # except IndexError:
    #     ckk = 0
    # print(ckk)
    except:
        ckk = 0
        logging.info('返回值报错')
    self.rdb.set('ELKRequestStatus-{}-{}'.format(app_code, i), ckk)
    return ['ELK 域名访问状态码数据入库', domain_name, 'request_status: {}'.format(i),
            '时间：{}:{}~{}'.format(today, start_, end_), ckk]
    # try:
    #     # ckk = resp_data['aggregations']['3']['buckets']['400.0-599.0']['5']['buckets']
    #     ckk = resp_data['aggregations']['3']['buckets']['400.0-599.0']['doc_count']
    # # ckk = resp_data['aggregations']['2']['buckets'][-1]['doc_count']
    #     self.rdb.set('ELKRequestStatus-{}-{}'.format(app_code, status), ckk)
    #     return ['ELK 域名访问状态码数据入库', domain_name, 'request_status: {}'.format(status),
    #             '时间：{}:{}~{}'.format(today, start_, end_), ckk]
    #     if ckk(type) not in int:
    #         logging.info('value值错误')
    # except:
    #      logging.info('返回值报错')

    # try:
    #     for key, value in resp_data['aggregations']['3']['buckets']['200.0-599.0']['5']['buckets'].items():
    #         if '300' in key:
    #             count_3xx = value['doc_count']
    #         elif '400' in key:
    #             count_4xx = value['doc_count']
    #         elif '500' in key:
    #             count_5xx = value['doc_count']
    #         else:
    #             continue
    # except:
    #     logging.info('返回值报错')
    # return count_3xx,count_4xx,count_5xx
    # CKK = logging.info('域名：{}, 时间：{}:{}~{}, 数据: {} - {} - {}'.format(domain_name, today, start_, end_, count_3xx, count_4xx,
    # count_5xx))
    # print(CKK)
    # 将统计的数据写入 redis
    # self.rdb.set('ELKRequestStatus-{}-3xx'.format(app_code), count_3xx)
    # self.rdb.set('ELKRequestStatus-{}-4xx'.format(app_code), count_4xx)
    # self.rdb.set('ELKRequestStatus-{}-5xx'.format(app_code), count_5xx)
    # return ['ELK 域名访问状态码数据入库', domain_name, '3xx: {}'.format(count_3xx), '4xx: {}'.format(count_4xx),
    #         '5xx: {}'.format(count_5xx), '时间：{}:{}~{}'.format(today, start_, end_)]


@elk_request_status.task(base=ELKRquestStatus, bind=True, max_retries=3)
def elk_request_status_scheduling(self, times):
    '''
        任务调度
        2023-02-27
    '''
    today_date = time.strftime("%Y.%m.%d", time.localtime(time.time() - 24 * 60 * 60))
    time_now = int(time.time() * 1000)
    time_start = time_now - 60 * times * 1000
    # today_date = '2023.02.26'
    # time_start = 1677340800000
    # time_now = 1677427199999
    # app_code_list = ['bestpay', 'bsb', 'zjrcu', 'icbc', 'ceb', 'jsrcu', 'huanbei', 'rxjt', 'oklife', 'cmbc', 'ccb',
    #                  'neigou', 'fdbank', 'blm', 'allinpay', 'fafuli', 'anyolife', 'mi', '91ala', 'cxa', 'qd', '00bang',
    #                  'srcb', 'mallicbc', 'rizhaobank', 'qilubank', 'yantaibank', 'sxccb', 'fsg', 'jiningbank',
    #                  'dongyingbank', 'shrb', 'linshangbank', 'hnnx', 'guilinbank', 'csrcmb', 'whccb', 'bhb', 'bhbank']
    # 监控巡检客户 光大银行、翼支付、渤海银行、云闪付、百联、通联钱包、厦门国际银行
    # app_code_list = ['ceb','bestpay','bhbank','unionpay','oklife','allinpay','xib']
    app_code_list = ['ceb','bestpay','bhbank','unionpay','oklife','allinpay','xib']
    requset_status = [400, 401, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 500, 501,
                      502, 503, 504, 505]
    for i in requset_status:
        for app_code in app_code_list:
            get_elk_request_status_by_appcode.apply_async(args=[app_code, today_date, time_start, time_now,i],
                                                            queue="yunwei_elk_request_status_tasks")
        return [app_code_list, today_date, time_start, time_now]


@elk_request_status.task(base=ELKRquestStatus, bind=True, max_retries=3)
def get_fetch_slow_from_redis(self, app_code, status):
    for i in range(400, 599):
        if i == 402 or 505 < i < 599 or 417 < i < 500:
            logging.info('不在监控状态码范围内')
            continue
        else:
            resp = self.rdb.get('ELKRequestStatus-{}-{}'.format(app_code,status))
        return  resp
#     '''
#         根据 appCode 、status_level 获取相应的redis数据
#         2020-07-13
#     '''
#     for i in range(400, 599):
#         if i == 402 or 505 < i < 599 or 417 < i < 500:
#             logging.info('不在监控状态码范围内')
#             continue
#         else:
#             resp = self.rdb.get('ELKRequestStatus-{}-{}'.format(app_code,)) or 0
#       return resp
#     if status_level == '3xx':
#         resp = self.rdb.get('ELKRequestStatus-{}-3xx'.format(app_code)) or 0
#     elif status_level == '4xx':
#         resp = self.rdb.get('ELKRequestStatus-{}-4xx'.format(app_code)) or 0
#     elif status_level == '5xx':
#         resp = self.rdb.get('ELKRequestStatus-{}-5xx'.format(app_code)) or 0
#     else:
#         resp = 0
#     return resp


if __name__ == '__main__':
    # python3 /etc/zabbix/oto_saas_yunwei/elk_request_status_worker.py bestpay 3xx
    # app_code = 'hnnx'
    # status_level = '400'
    # elk_request_status_scheduling(30)
    # print(app_code, status_level)
    # print(app_code)
    # app_code = 'bhbank'
    # status_level = 403
    # status_level = 404
    # # status_level = sys.argv[2]
    app_code = sys.argv[1]
    status_level = sys.argv[2]
    count = get_fetch_slow_from_redis(app_code, status_level)
    print(count)